package message;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import message.types.data.AddDataRequest;
import message.types.data.GetAllDatasAnswer;
import message.types.data.GetLastDataAnswer;
import message.types.message.RejectedRequest;
import message.types.none.GetAllDatasRequest;
import message.types.none.GetLastDataRequest;
import message.types.none.NewDataNotification;
import message.types.stalker.CreateRoomSuccessAnswer;
import message.types.stalker.LogOffNotification;
import message.types.stalker.LoginSuccessAnswer;
import message.types.stalker.RegisterRequest;
import message.types.stalkerstring.GetRoomFromNameAnswer;
import message.types.stalkerstring.GetUserFromNameAnswer;
import message.types.string.CreatePrivatePersistentRoomRequest;
import message.types.string.CreateRoomRequest;
import message.types.string.GetRoomFromNameRequest;
import message.types.string.GetUserFromNameRequest;
import message.types.string.LoginRequest;
import message.types.stringstring.LoginFailedAnswer;
import message.types.unique.EmptyMessage;
import message.types.unique.RoomInvitation;
import network.e2e.FrameReader;
import network.e2e.FrameWriter;
import network.link.FrameInputStream;
import network.link.FrameOutputStream;

import org.junit.Assert;
import org.junit.Test;

import stalker.room.PrivatePersistentRoom;
import stalker.room.Room;
import stalker.user.User;
import data.Data;
import data.content.Content;
import data.content.ContentSentence;
import data.content.ContentStalkerJoin;
import data.datas.CompleteHistoryDatas;
import data.datas.Datas;

/**
 * JUnit test for messageparser
 */

public class MessageParserTest {
  
  @Test
  public void testAddDataRequest() throws IOException {
    User terong = User.createUser("Terongman!");
    Room ruang = PrivatePersistentRoom.create("Leaderboard");
    Content testdata = new ContentSentence("Irvan tu ganteng tau!\n ah ah ");
    Message test = new AddDataRequest(terong, ruang, testdata);
    Message exp = new AddDataRequest(terong, ruang, testdata);
    
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testGetLastDataAnswer() throws IOException {
    User apel = User.createUser("Manusia 1/2 Apel");
    Room ruang = PrivatePersistentRoom.create("Just Fruity!");
    Content testdata = new ContentSentence("Kamu mau jus apa?");
    Message test = new GetLastDataAnswer(ruang, apel, new Data(apel, testdata));
    Message exp = new GetLastDataAnswer(ruang, apel, new Data(apel, testdata));

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testGetLastDataRequest() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new GetLastDataRequest(ruang, apel);
    Message exp = new GetLastDataRequest(ruang, apel);

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testRegisterRequest() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new RegisterRequest(ruang, apel);
    Message exp = new RegisterRequest(ruang, apel);

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testLoginRequest() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new LoginRequest(ruang, apel, "Juice");
    Message exp = new LoginRequest(ruang, apel, "Juice");

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testSuccessAnswer() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new LoginSuccessAnswer(ruang, apel, apel);
    Message exp = new LoginSuccessAnswer(ruang, apel, apel);

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testFailedLogin() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new LoginFailedAnswer(ruang, apel, "Irvan", "Kurang jelek");
    Message exp = new LoginFailedAnswer(ruang, apel, "Irvan", "Kurang jelek");

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testCreateRoom() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new CreateRoomRequest(ruang, apel, "Juice");
    Message exp = new CreateRoomRequest(ruang, apel, "Juice");

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testGetCreateRoom() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new CreateRoomSuccessAnswer(ruang, apel, apel);
    Message exp = new CreateRoomSuccessAnswer(ruang, apel, apel);

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  public void testGetCreatePPRoom() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new CreatePrivatePersistentRoomRequest(ruang, apel, "kiss");
    Message exp = new CreatePrivatePersistentRoomRequest(ruang, apel, "Kiss");

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  
  @Test
  public void testRoomInvitation() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new RoomInvitation(ruang, apel, ruang, apel);
    Message exp = new RoomInvitation(ruang, apel, ruang, apel);

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testGetAllDatasReq() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new GetAllDatasRequest(apel, ruang);
    Message exp = new GetAllDatasRequest(apel, ruang);

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void GetAllDatasAnswer() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Datas datas = new CompleteHistoryDatas();
    datas.addData(apel, new ContentSentence("pisang"));
    datas.addData(apel, new ContentStalkerJoin(apel));
    Message test = new GetAllDatasAnswer(ruang, apel, datas);
    Message exp = new GetAllDatasAnswer(ruang, apel, datas);

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void GetUserFromNameRequest() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new GetUserFromNameRequest(ruang, apel, "Manusia 1/2 Apel");
    Message exp = new GetUserFromNameRequest(ruang, apel, "Manusia 1/2 Apel");

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void GetUserFromNameAnswer() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new GetUserFromNameAnswer(ruang, apel, apel, "Manusia 1/2 Apel");
    Message exp = new GetUserFromNameAnswer(ruang, apel, apel, "Manusia 1/2 Apel");

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testNewDataNotification() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new NewDataNotification(ruang, apel);
    Message exp = new NewDataNotification(ruang, apel);

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testLogOffNotification() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new LogOffNotification(ruang, apel, apel);
    Message exp = new LogOffNotification(ruang, apel, apel);

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testGetRoomFromNameRequest() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new GetRoomFromNameRequest(ruang, apel, "Manusia 1/2 Apel");
    Message exp = new GetRoomFromNameRequest(ruang, apel, "Manusia 1/2 Apel");

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testGetRoomFromNameAnswer() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message test = new GetRoomFromNameAnswer(ruang, apel, apel, "Manusia 1/2 Apel");
    Message exp = new GetRoomFromNameAnswer(ruang, apel, apel, "Manusia 1/2 Apel");

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testRejectedRequest() throws IOException {
    User apel = User.getUserFromName("Manusia 1/2 Apel");
    Room ruang = Room.getRoomFromName("Just Fruity!");
    Message msg1 = new GetRoomFromNameAnswer(ruang, apel, apel, "Manusia 1/2 Apel");
    Message msg2 = new GetRoomFromNameAnswer(ruang, apel, apel, "Manusia 1/2 Apel");

    Message test = new RejectedRequest(ruang, apel, msg1);
    Message exp = new RejectedRequest(ruang, apel, msg2);

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
  @Test
  public void testEmptyMessage() throws IOException {
    
    Message test = new EmptyMessage();
    Message exp = new EmptyMessage();

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    FrameWriter fw = new FrameWriter(new FrameOutputStream(os));
    
    MessageParser.send(test, fw);
    
    FrameReader fr = new FrameReader(new FrameInputStream(new ByteArrayInputStream(os.toByteArray())));
    
    System.out.println(os.toString());
    
    Message stalk = MessageParser.retrieve(fr);
    
    Assert.assertEquals(stalk, test);
    Assert.assertEquals(stalk, exp);
  }
  
}
